#include <iostream>
#include <thread>
#include <future>
#include <memory>

int add(int num1, int num2) 
{
    std::this_thread::sleep_for(std::chrono::seconds(3));
    return num1 + num2;
}

int main()
{
#if 0
    // 将一个函数封装为packaged_task对象, 可以直接被执行
    std::packaged_task<int(int, int)> task(add);
    std::future<int> fut = task.get_future();
    // task(1, 2);

    // 但是无法直接被当作一个函数对象进行传递
    // std::async(std::launch::async, task, 1, 2);
    std::thread thr(std::move(task), 1, 2);

    std::cout << fut.get() << '\n';
    thr.join();
#endif

    // 常将packaged_task封装为指针, 并采用RAII思想规避由于生命周期带来的问题
    auto task = std::make_shared<std::packaged_task<int(int, int)>>(add);
    std::future<int> fut = task->get_future();
    // 对task封装一层lambdad对象, 作为参数传递给线程
    std::thread thr([task](){
        (*task)(1, 2);
    });
    std::cout << fut.get() << '\n';
    thr.join();
    return 0;
}